package com.xiaoye.qbproject.service.impl;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.px.jni.interfaceDDS;
import com.xiaoye.qbproject.dds.DdsPublisherConfig;
import com.xiaoye.qbproject.domain.MqRead;
import com.xiaoye.qbproject.domain.QbSubjectArticle;
import com.xiaoye.qbproject.domain.QbSubjectSubscription;
import com.xiaoye.qbproject.domain.model.DdsMessageDto;
import com.xiaoye.qbproject.domain.wiki.QbPublishVo;
import com.xiaoye.qbproject.mapper.MqReadMapper;
import com.xiaoye.qbproject.mapper.QbSubjectArticleMapper;
import com.xiaoye.qbproject.mapper.QbSubjectMapper;
import com.xiaoye.qbproject.mapper.QbSubjectSubscriptionMapper;
import com.xiaoye.qbproject.service.QbSubjectArticleService;
import com.xiaoye.qbproject.util.DateUtils;
import com.xiaoye.qbproject.util.StringUtils;
import com.xiaoye.qbproject.vo.QbSubjectArticleVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Administrator
 * @description 针对表【QB_SUBJECT_ACTICLE(专题文章)】的数据库操作Service实现
 * @createDate 2025-01-15 19:50:48
 */
@Slf4j
@Service
public class QbSubjectArticleServiceImpl extends ServiceImpl<QbSubjectArticleMapper, QbSubjectArticle>
        implements QbSubjectArticleService {

    @Value("${dds.articleUrl}")
    private String articleUrl;

    @Autowired
    private QbSubjectSubscriptionMapper qbSubjectSubscriptionMapper;
    @Autowired
    private QbSubjectArticleMapper qbSubjectArticleMapper;
    @Autowired
    private QbSubjectMapper qbSubjectMapper;

    @Autowired
    private MqReadMapper mqReadMapper;

    @Autowired
    private interfaceDDS pDDS;

    @Autowired
    DdsPublisherConfig ddsPublisherConfig;

    /**
     * @param vo
     * @description: 获取专题文章列表
     * @author: ChenYao
     * @return: java.util.List<com.xiaoye.qbproject.domain.QbSubjectArticle>
     * @ceateDate: 2025/1/15 下午8:03
     */
    @Override
    public List<QbSubjectArticle> getArticleList(QbSubjectArticleVo vo) {

        LambdaQueryWrapper<QbSubjectArticle> queryWrapper = Wrappers
                .<QbSubjectArticle>lambdaQuery()
                .select(QbSubjectArticle.class, fields -> !fields.getColumn().equalsIgnoreCase("CONTENT"))
                .orderByDesc(QbSubjectArticle::getCreateTime, QbSubjectArticle::getReleaseTime);
        String subjectId = vo.getSubjectId();
        if (StringUtils.isNotBlank(subjectId)) {
            queryWrapper.eq(QbSubjectArticle::getSubjectId, subjectId);
        }
        String title = vo.getTitle();
        if (StringUtils.isNotBlank(title)) {
            queryWrapper.like(QbSubjectArticle::getTitle, title);
        }
        // 根据最近几天查询
        Integer recentDays = vo.getRecentDays();
        if (recentDays != null && recentDays > 0) {
            queryWrapper.ge(QbSubjectArticle::getReleaseTime, DateUtils.getRecentDays(recentDays));
        }
        // 根据开始时间和结束时间 区间查询
        Date beginTime = vo.getBeginTime();
        Date endTime = vo.getEndTime();
        if (beginTime != null && endTime != null) {
            queryWrapper.ge(QbSubjectArticle::getReleaseTime, beginTime);
            queryWrapper.le(QbSubjectArticle::getReleaseTime, endTime);
        }

        return baseMapper.selectList(queryWrapper);
    }


    /**
     * @param qbSubjectArticle
     * @description: 添加专题文章
     * @author: ChenYao
     * @return: int
     * @ceateDate: 2025/1/17 下午7:22
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int add(QbSubjectArticle qbSubjectArticle) {
        qbSubjectMapper.updateSubjectLastUpdateTime(qbSubjectArticle.getSubjectId(), new Date());
        int insert = baseMapper.insert(qbSubjectArticle);
        sendArticle(qbSubjectArticle);
        return insert;
    }

    private void sendArticle(QbSubjectArticle qbSubjectArticle) {
        // 查询订阅该专题的所有用户,依次发送MQ消息
        String subjectId = qbSubjectArticle.getSubjectId();
        List<QbSubjectSubscription> qbSubjectSubscriptions = qbSubjectSubscriptionMapper.selectList(Wrappers
                .lambdaQuery(QbSubjectSubscription.class)
                .eq(QbSubjectSubscription::getSubjectId, subjectId)
        );
        if (CollectionUtils.isEmpty(qbSubjectSubscriptions)) {
            log.info("没有用户订阅[{}]专题", qbSubjectArticle.getTitle());
            return;
        }
        Set<String> userIdSet = qbSubjectSubscriptions.stream()
                .map(QbSubjectSubscription::getUserId)
                .collect(Collectors.toSet()
                );
        log.info("订阅[{}]专题的用户Set:{}", qbSubjectArticle.getTitle(), userIdSet);
        DdsMessageDto ddsMessageDto = new DdsMessageDto();
        //ddsMessageDto.setSendName("userId");
        // userIdSet 转字符串 逗号分隔
        ddsMessageDto.setReceiveName(String.join(",", userIdSet));
        ddsMessageDto.setReceiveCunt(userIdSet.size());
        ddsMessageDto.setMessageCode(2);
        ddsMessageDto.setDescription(qbSubjectArticle.getTitle());
        DdsMessageDto.Params params = new DdsMessageDto.Params();
        params.setUrlPath(articleUrl + qbSubjectArticle.getId());
        ddsMessageDto.setParams(params);
        pDDS.DE_DDS_SendMessage(DdsPublisherConfig.pDomain, DdsPublisherConfig.pHandle, ddsPublisherConfig.topicName, JSONObject.toJSONString(ddsMessageDto));
        log.info("发送消息给用户:{}", userIdSet);
    }

    /**
     * @param qbSubjectArticle
     * @description: 编辑专题文章
     * @author: ChenYao
     * @return: int
     * @ceateDate: 2025/1/17 下午7:22
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int editById(QbSubjectArticle qbSubjectArticle) {
        qbSubjectMapper.updateSubjectLastUpdateTime(qbSubjectArticle.getSubjectId(), new Date());
        int updateById = baseMapper.updateById(qbSubjectArticle);
        sendArticle(qbSubjectArticle);
        return updateById;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public int publish(QbPublishVo qbPublishVo) {
        String qbArticleId = qbPublishVo.getId();
        QbSubjectArticle qbSubjectArticle = new QbSubjectArticle();
        qbSubjectArticle.setId(qbArticleId);
        qbSubjectArticle.setIsPublish(qbPublishVo.getIsPublish());

        if (baseMapper.updateById(qbSubjectArticle) == 0) {
            throw new RuntimeException("文章不存在");
        }
        if (Boolean.FALSE.equals(qbSubjectArticle.getIsPublish())) {
            // 如果是取消发布,则删除 已读内容
            mqReadMapper.delete(Wrappers.<MqRead>lambdaQuery().eq(MqRead::getMsgId, qbArticleId));
        } else {
            QbSubjectArticle oldQbSubjectArticle = baseMapper.selectById(qbArticleId);

            // 查询订阅该专题的所有用户,依次发送MQ消息
            String subjectId = oldQbSubjectArticle.getSubjectId();
            List<QbSubjectSubscription> qbSubjectSubscriptions = qbSubjectSubscriptionMapper.selectList(Wrappers
                    .lambdaQuery(QbSubjectSubscription.class)
                    .eq(QbSubjectSubscription::getSubjectId, subjectId)
            );

            List<String> roleNames = qbPublishVo.getRoleNames();
            // 有人订阅专题,则发送MQ消息
            if (CollectionUtils.isNotEmpty(qbSubjectSubscriptions) && CollectionUtils.isEmpty(roleNames)) {
                Set<String> userIdSet = qbSubjectSubscriptions.stream()
                        .map(QbSubjectSubscription::getUserId)
                        .collect(Collectors.toSet()
                        );
                log.info("订阅[{}]专题的用户Set:{}", oldQbSubjectArticle.getTitle(), userIdSet);
                DdsMessageDto ddsMessageDto = new DdsMessageDto();
                //ddsMessageDto.setSendName("userId");
                // userIdSet 转字符串 逗号分隔
                ddsMessageDto.setReceiveName(String.join(",", userIdSet));
                ddsMessageDto.setReceiveCunt(userIdSet.size());
                ddsMessageDto.setMessageCode(2);
                ddsMessageDto.setDescription(oldQbSubjectArticle.getTitle());
                DdsMessageDto.Params params = new DdsMessageDto.Params();
                params.setUrlPath(articleUrl + oldQbSubjectArticle.getId());
                ddsMessageDto.setParams(params);
                pDDS.DE_DDS_SendMessage(DdsPublisherConfig.pDomain, DdsPublisherConfig.pHandle, ddsPublisherConfig.topicName, JSONObject.toJSONString(ddsMessageDto));
                log.info("发送消息给用户:{}", userIdSet);

            }
            // 如果有角色,则发送MQ消息给对应角色
            if (CollectionUtils.isNotEmpty(roleNames)) {
                DdsMessageDto ddsMessageDto = new DdsMessageDto();
                ddsMessageDto.setSendName(qbPublishVo.getRoleName());
                ddsMessageDto.setReceiveName(String.join(",", roleNames));
                ddsMessageDto.setReceiveCunt(roleNames.size());
                ddsMessageDto.setMessageCode(1);
                ddsMessageDto.setDescription(oldQbSubjectArticle.getTitle());
                DdsMessageDto.Params params = new DdsMessageDto.Params();
                params.setUrlPath(articleUrl + oldQbSubjectArticle.getId());

                ddsMessageDto.setParams(params);
                pDDS.DE_DDS_SendMessage(DdsPublisherConfig.pDomain, DdsPublisherConfig.pHandle, ddsPublisherConfig.topicName, JSONObject.toJSONString(ddsMessageDto));
                log.info("发送消息给角色:{}", roleNames);
            }

        }
        // 更新文章发布状态
        return baseMapper.updateById(qbSubjectArticle);
    }


    @Override
    public Long getPublishedCount(String userId) {
        // 获取已订阅的文章
        List<QbSubjectSubscription> qbSubjectSubscriptions = qbSubjectSubscriptionMapper.selectList(Wrappers
                .<QbSubjectSubscription>lambdaQuery()
                .eq(QbSubjectSubscription::getUserId, userId)
        );
        if (CollectionUtils.isEmpty(qbSubjectSubscriptions)) {
            return 0L;
        }
        Set<String> subjectIds = qbSubjectSubscriptions.stream()
                .map(QbSubjectSubscription::getSubjectId)
                .collect(Collectors.toSet());
        // 查询已读得专题文章
        List<String> articleIds = mqReadMapper.selectList(Wrappers
                        .<MqRead>lambdaQuery()
                        .eq(MqRead::getUserId, userId))
                .stream()
                .map(MqRead::getMsgId)
                .collect(Collectors.toList());
        // 查询专题下 已发布的文章
        return qbSubjectArticleMapper.selectCount(Wrappers.<QbSubjectArticle>lambdaQuery()
                .in(QbSubjectArticle::getSubjectId, subjectIds)
                .eq(QbSubjectArticle::getIsPublish, 1)
                .notIn(CollectionUtils.isNotEmpty(articleIds), QbSubjectArticle::getId, articleIds)
        );
    }

    @Override
    public List<QbSubjectArticle> getPublishedArticles(String userId, Boolean isFilterRead) {
        // 获取已订阅的文章
        List<QbSubjectSubscription> qbSubjectSubscriptions = qbSubjectSubscriptionMapper.selectList(Wrappers
                .<QbSubjectSubscription>lambdaQuery()
                .eq(QbSubjectSubscription::getUserId, userId)
        );
        if (CollectionUtils.isEmpty(qbSubjectSubscriptions)) {
            return Collections.emptyList();
        }
        Set<String> subjectIds = qbSubjectSubscriptions.stream()
                .map(QbSubjectSubscription::getSubjectId)
                .collect(Collectors.toSet());
        List<String> articleIds = null;
        if (Boolean.TRUE.equals(isFilterRead)) {
            // 查询已读得专题文章
            articleIds = mqReadMapper.selectList(Wrappers
                            .<MqRead>lambdaQuery()
                            .eq(MqRead::getUserId, userId))
                    .stream()
                    .map(MqRead::getMsgId)
                    .collect(Collectors.toList());
        }

        return qbSubjectArticleMapper.selectList(Wrappers.<QbSubjectArticle>lambdaQuery()
                .in(QbSubjectArticle::getSubjectId, subjectIds)
                .eq(QbSubjectArticle::getIsPublish, 1)
                .notIn(CollectionUtils.isNotEmpty(articleIds), QbSubjectArticle::getId, articleIds)
                .select(QbSubjectArticle::getTitle, QbSubjectArticle::getId,
                        QbSubjectArticle::getSource, QbSubjectArticle::getReleaseTime, QbSubjectArticle::getIntro)
        );
    }

    @Override
    public void saveOrUpdateArtBatch(List<QbSubjectArticle> subjectArticleList) {

        this.saveOrUpdateBatch(subjectArticleList);
        for (QbSubjectArticle qbSubjectArticle : subjectArticleList) {
            sendArticle(qbSubjectArticle);
        }

    }

}
